/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Microsoft.VisualStudio.CommandBars;

namespace DaveSexton.DocProject
{
	public class MenuCommand : VSCommand
	{
		#region Public Properties
		public sealed override string Name
		{
			get
			{
				return name;
			}
		}

		public sealed override bool UseOfficeBitmapResourceId
		{
			get
			{
				return useOfficeBitmapResourceId;
			}
		}

		public sealed override int OfficeBitmapResourceId
		{
			get
			{
				return officeBitmapResourceId;
			}
		}

		public sealed override Image Image
		{
			get
			{
				return image;
			}
		}

		public sealed override Color ImageTransparencyKey
		{
			get
			{
				return imageTransparencyKey;
			}
		}

		[CLSCompliant(false)]
		public override EnvDTE80.vsCommandStyle Style
		{
			get
			{
				return (image != null)
					? EnvDTE80.vsCommandStyle.vsCommandStylePictAndText
					: EnvDTE80.vsCommandStyle.vsCommandStyleText;
			}
		}

		[CLSCompliant(false)]
		public virtual CommandBar Parent
		{
			get
			{
				return parent;
			}
		}

		public virtual int Location
		{
			get
			{
				return location;
			}
			set
			{
				location = value;
			}
		}
		#endregion

		#region Private / Protected
		private readonly CommandBar parent;
		private readonly string name;
		private readonly bool useOfficeBitmapResourceId = true;
		private readonly int officeBitmapResourceId;
		private readonly Image image;
		private readonly Color imageTransparencyKey;
		private int location;	 // the default value of 0 indicates to DocProjec that the command should be appended
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="MenuCommand" /> class.
		/// </summary>
		public MenuCommand(string name)
		{
			if (string.IsNullOrEmpty(name))
				throw new ArgumentException(Resources.Errors.NullOrEmpty, "name");

			this.parent = VSEnvironmentHost.GetCommandBar("Tools");
			this.name = name;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MenuCommand" /> class.
		/// </summary>
		public MenuCommand(string name, int officeBitmapResourceId)
			: this(name)
		{
			this.officeBitmapResourceId = officeBitmapResourceId;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MenuCommand" /> class.
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily")]		// FxCop bug
		public MenuCommand(string name, Image image)
			: this(name)
		{
			this.image = image;

			useOfficeBitmapResourceId = false;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MenuCommand" /> class.
		/// </summary>
		public MenuCommand(string name, Image image, Color imageTransparencyKey)
			: this(name, image)
		{
			this.imageTransparencyKey = imageTransparencyKey;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MenuCommand" /> class.
		/// </summary>
		public MenuCommand(string commandBarName, string name)
		{
			if (string.IsNullOrEmpty(name))
				throw new ArgumentException(Resources.Errors.NullOrEmpty, "name");

			this.parent = VSEnvironmentHost.GetCommandBar(commandBarName);
			this.name = name;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MenuCommand" /> class.
		/// </summary>
		public MenuCommand(string commandBarName, string name, int officeBitmapResourceId)
			: this(commandBarName, name)
		{
			this.officeBitmapResourceId = officeBitmapResourceId;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MenuCommand" /> class.
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily")]		// FxCop bug
		public MenuCommand(string commandBarName, string name, Image image)
			: this(commandBarName, name)
		{
			this.image = image;

			useOfficeBitmapResourceId = false;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MenuCommand" /> class.
		/// </summary>
		public MenuCommand(string commandBarName, string name, Image image, Color imageTransparencyKey)
			: this(commandBarName, name, image)
		{
			this.imageTransparencyKey = imageTransparencyKey;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MenuCommand" /> class.
		/// </summary>
		[CLSCompliant(false)]
		public MenuCommand(CommandBar parent, string name)
		{
			if (parent == null)
				throw new ArgumentNullException("parent");

			if (string.IsNullOrEmpty(name))
				throw new ArgumentException(Resources.Errors.NullOrEmpty, "name");

			this.parent = parent;
			this.name = name;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MenuCommand" /> class.
		/// </summary>
		[CLSCompliant(false)]
		public MenuCommand(CommandBar parent, string name, int officeBitmapResourceId)
			: this(parent, name)
		{
			this.officeBitmapResourceId = officeBitmapResourceId;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MenuCommand" /> class.
		/// </summary>
		[CLSCompliant(false)]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily")]		// FxCop bug
		public MenuCommand(CommandBar parent, string name, Image image)
			: this(parent, name)
		{
			this.image = image;

			useOfficeBitmapResourceId = false;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MenuCommand" /> class.
		/// </summary>
		[CLSCompliant(false)]
		public MenuCommand(CommandBar parent, string name, Image image, Color imageTransparencyKey)
			: this(parent, name, image)
		{
			this.imageTransparencyKey = imageTransparencyKey;
		}
		#endregion

		#region Methods
		public sealed override object Execute(object option, object argument)
		{
			OnExecuted(EventArgs.Empty);

			return null;
		}
		#endregion

		#region Events
		private readonly object ExecutedEvent = new object();

		/// <summary>
		/// Event raised when the menu command is executed.
		/// </summary>
		public event EventHandler Executed
		{
			add
			{
				lock (ExecutedEvent)
				{
					Events.AddHandler(ExecutedEvent, value);
				}
			}
			remove
			{
				lock (ExecutedEvent)
				{
					Events.RemoveHandler(ExecutedEvent, value);
				}
			}
		}

		/// <summary>
		/// Raises the <see cref="Executed" /> event.
		/// </summary>
		/// <param name="e"><see cref="EventArgs" /> object that provides the arguments for the event.</param>
		protected virtual void OnExecuted(EventArgs e)
		{
			EventHandler handler = null;

			lock (ExecutedEvent)
			{
				handler = (EventHandler) Events[ExecutedEvent];
			}

			if (handler != null)
				handler(this, e);
		}
		#endregion
	}
}
